/*!
 * \file HisDataMgr.cpp
 * \project WonderTrader
 *
 * \author Wesley
 * \date 2020/03/30
 * 
 * \brief 历史数据管理器实现文件
 * 
 * \details 本文件实现了HisDataMgr类的各种方法，用于在WonderTrader回测框架中管理历史数据的读取和处理。
 *          主要实现功能包括：
 *          - 动态加载数据存储模块
 *          - 初始化数据读取器
 *          - 提供K线数据读取接口
 *          - 提供Tick数据读取接口
 *          - 统一的日志回调处理
 */
#include "HisDataMgr.h"
#include "WtHelper.h"
#include "../Share/DLLHelper.hpp"
#include "../Includes/WTSVariant.hpp"
#include "../WTSTools/WTSLogger.h"

/*!
 * \brief 数据读取器日志回调函数
 * 
 * \param ll 日志级别
 * \param message 日志消息内容
 * 
 * \details 用于处理数据读取器产生的日志信息。该函数作为回调接口，
 *          将数据读取器的日志信息转发到WonderTrader的统一日志系统中。
 *          这样可以确保所有组件的日志都能统一管理和输出。
 *          
 *          功能特点：
 *          - 统一日志输出格式
 *          - 支持多种日志级别
 *          - 与WTSLogger系统集成
 */
void HisDataMgr::reader_log(WTSLogLevel ll, const char* message)
{
	WTSLogger::log_raw(ll, message);
}

/*!
 * \brief 初始化历史数据管理器
 * 
 * \param cfg 配置参数
 * \return 初始化是否成功
 * 
 * \details 根据配置参数初始化历史数据管理器。主要完成以下工作：
 *          1. 从配置中获取数据存储模块名称
 *          2. 动态加载指定的数据存储模块
 *          3. 获取数据读取器创建函数
 *          4. 创建并初始化数据读取器实例
 *          
 *          模块加载逻辑：
 *          - 如果配置中指定了module，则加载指定模块
 *          - 如果未指定，则默认加载"WtDataStorage"模块
 *          - 模块路径会自动添加实例目录前缀和平台相关后缀
 *          
 *          错误处理：
 *          - 模块加载失败时记录错误日志
 *          - 函数符号查找失败时记录错误日志
 *          - 但函数仍然返回true以保持向后兼容性
 */
bool HisDataMgr::init(WTSVariant* cfg)
{
	// 从配置中获取数据存储模块名称
	std::string module = cfg->getCString("module");
	if (module.empty())
		// 如果未指定模块，使用默认的WtDataStorage模块
		module = WtHelper::getInstDir() + DLLHelper::wrap_module("WtDataStorage");
	else
		// 使用配置指定的模块
		module = WtHelper::getInstDir() + DLLHelper::wrap_module(module.c_str());

	// 动态加载数据存储模块
	DllHandle libParser = DLLHelper::load_library(module.c_str());
	if (libParser)
	{
		// 获取数据读取器创建函数
		FuncCreateBtDtReader pFuncCreator = (FuncCreateBtDtReader)DLLHelper::get_symbol(libParser, "createBtDtReader");
		if (pFuncCreator == NULL)
		{
			WTSLogger::error_f("Initializing of backtest data reader failed: function createBtDtReader not found...");
		}

		// 创建数据读取器实例
		if (pFuncCreator)
		{
			_reader = pFuncCreator();
		}

		WTSLogger::debug_f("Back data storage module {} loaded", module);
	}
	else
	{
		WTSLogger::error_f("Loading module back data storage module {} failed", module);

	}

	// 初始化数据读取器，传入配置和日志回调
	_reader->init(cfg, this);

	return true;
}

/*!
 * \brief 加载原始K线数据
 * 
 * \param exchg 交易所代码
 * \param code 合约代码
 * \param period K线周期类型
 * \param cb 数据加载完成回调函数
 * \return 数据加载是否成功
 * 
 * \details 从数据存储中加载指定合约的原始K线数据。该函数会调用底层数据读取器
 *          来获取数据，并通过回调函数将数据传递给调用者。这种异步回调的设计
 *          可以避免大量数据在内存中的重复拷贝，提高性能。
 *          
 *          执行流程：
 *          1. 检查数据读取器是否已初始化
 *          2. 调用数据读取器读取原始K线数据
 *          3. 如果读取成功，调用回调函数传递数据
 *          
 *          错误处理：
 *          - 数据读取器未初始化时返回false并记录错误日志
 *          - 数据读取失败时返回false但不调用回调函数
 */
bool HisDataMgr::load_raw_bars(const char* exchg, const char* code, WTSKlinePeriod period, FuncLoadDataCallback cb)
{
	// 检查数据读取器是否已初始化
	if(_reader == NULL)
	{
		WTSLogger::log_raw(LL_ERROR, "Backtest Data Reader not initialized");
		return false;
	}

	// 调用数据读取器读取原始K线数据
	std::string buffer;
	bool bSucc = _reader->read_raw_bars(exchg, code, period, buffer);
	if (bSucc)
		// 数据读取成功，通过回调函数传递数据
		cb(buffer);
	return bSucc;
}

/*!
 * \brief 加载原始Tick数据
 * 
 * \param exchg 交易所代码
 * \param code 合约代码
 * \param uDate 数据日期（格式：YYYYMMDD）
 * \param cb 数据加载完成回调函数
 * \return 数据加载是否成功
 * 
 * \details 从数据存储中加载指定合约指定日期的原始Tick数据。该函数会调用底层
 *          数据读取器来获取数据，并通过回调函数将数据传递给调用者。Tick数据
 *          通常数据量较大，使用回调方式可以提高内存使用效率。
 *          
 *          执行流程：
 *          1. 检查数据读取器是否已初始化
 *          2. 调用数据读取器读取指定日期的原始Tick数据
 *          3. 如果读取成功，调用回调函数传递数据
 *          
 *          数据格式：
 *          - uDate参数使用YYYYMMDD格式，如20231225表示2023年12月25日
 *          - 返回的数据包含该日期完整的Tick行情数据
 *          
 *          错误处理：
 *          - 数据读取器未初始化时返回false并记录错误日志
 *          - 数据读取失败时返回false但不调用回调函数
 */
bool HisDataMgr::load_raw_ticks(const char* exchg, const char* code, uint32_t uDate, FuncLoadDataCallback cb)
{
	// 检查数据读取器是否已初始化
	if (_reader == NULL)
	{
		WTSLogger::log_raw(LL_ERROR, "Backtest Data Reader not initialized");
		return false;
	}

	// 调用数据读取器读取指定日期的原始Tick数据
	std::string buffer;
	bool bSucc = _reader->read_raw_ticks(exchg, code, uDate, buffer);
	if (bSucc)
		// 数据读取成功，通过回调函数传递数据
		cb(buffer);
	return bSucc;
}